from flask import Flask, request, jsonify, g, current_app, session
from flask_jwt_extended import (
    JWTManager,
    get_jwt_identity,
    verify_jwt_in_request,
)
from flask_jwt_extended.exceptions import NoAuthorizationError, InvalidHeaderError, WrongTokenError, RevokedTokenError, \
    FreshTokenRequired
from config import Config
from extension import db
from flask_jwt_extended import decode_token
import socket
import os

from models import User, Role
from util.result import Result

app = Flask(__name__)
app.config.from_object(Config)  # 加载配置

# 初始化扩展
db.init_app(app)
jwt = JWTManager(app)
from routes.auth import api_bp as auth_bp
from routes.category import api_bp as category_bp
from routes.book import api_bp as book_bp
from routes.reader import api_bp as reader_bp
from routes.borrow import api_bp as borrow_bp
from routes.llm import api_bp as llm_bp
from routes.file import api_bp as file_bp
from routes.user import api_bp as user_bp
from routes.role import api_bp as role_bp
from routes.permission import api_bp as permission_bp
from routes.captcha import api_bp as captcha_bp
app.register_blueprint(auth_bp)
app.register_blueprint(category_bp)
app.register_blueprint(book_bp)
app.register_blueprint(reader_bp)
app.register_blueprint(borrow_bp)
app.register_blueprint(llm_bp)
app.register_blueprint(file_bp)
app.register_blueprint(user_bp)
app.register_blueprint(role_bp)
app.register_blueprint(permission_bp)
app.register_blueprint(captcha_bp)
@app.before_request
def verify_token():
    # 不需要拦截的路由
    exclude_routes = ['/login', '/register','/captcha']
    if request.path in exclude_routes or request.path.startswith('/static'):
        return

    try:
        # 从请求头中获取token
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return Result.error('无效的认证格式，请使用Bearer Token'), 401

        # 提取token（处理可能的空格问题）
        token = auth_header.split(' ')[1].strip()
        if not token:
            return Result.error('token不能为空'), 401

        # 手动验证JWT Token
        try:
            data = decode_token(token)
        except Exception as e:
            # 捕获所有token验证相关异常（过期、篡改等）
            current_app.logger.warning(f"token验证失败: {str(e)}")
            return Result.error('无效的token或token已过期'), 401

        # 获取用户身份
        user_id = data.get('sub')
        if not user_id:
            return Result.error('token中未包含用户信息'), 401

        user = db.session.get(User, user_id)
        if not user:
            return Result.error('token对应的用户不存在'), 401

        # 检查用户状态
        if user.status != 1:  # 假设1为正常状态
            return Result.error('该账号已被禁用，请联系管理员'), 403

        # 查询角色信息 - 使用Session.get()替代Query.get()
        role = db.session.get(Role, user.role_id) if user.role_id else None
        # 收集角色权限列表
        permissions = [perm.name for perm in role.permissions] if (role and role.permissions) else []

        # 存储用户信息到g对象
        g.current_user = {
            'id': user_id,
            'role_name': role.name if role else None,
            'permissions': permissions
        }

    except NoAuthorizationError:
        return Result.error('缺少认证token'), 401
    except Exception as e:
        current_app.logger.error(f"认证过程异常: {str(e)}")
        return Result.error('认证过程发生错误，请稍后重试'), 500


# 开发环境自动创建表（生产环境用迁移工具）
if __name__ == '__main__':
    with app.app_context():
        if app.config['DEBUG']:
            db.create_all()
    app.run(debug=app.config['DEBUG'])
